<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>component number</title>
    <script src="js/vue.js"></script>
</head>
<body>
    <div id="app">
        <p>{{value}}</p>
        <com-number v-bind:min="0" v-bind:max="10" v-bind:val="value" v-model="value"></com-number>
    </div>
</body>
<script>
    function isNumVal(_val) {
        return (/^-?\d+$/).test(_val + '');
    }
    Vue.component('com-number',{
        template:'<div><input type="text" :value="numVal" @change="inputChange"/>' +
                    '<button :disabled="min >= numVal " @click="reduce">-</button>' +
                    '<button :disabled="max <= numVal " @click="add">+</button>' +
                '</div>',
        props: {
            min: {
               type: Number,
               default: -Infinity
            },
            max: {
                type: Number,
                default: Infinity
            },
            val: {
                type: Number,
                default: 0
            }
        },
        data: function () {
          return {
              numVal: this.val
          }
        },
        methods: {
            reduce: function () {
                if(this.min < this.numVal){
                    this.updateValue(-- this.numVal );
                }
            },
            add: function () {
                if(this.max > this.numVal){
                    this.updateValue(++this.numVal );
                }
            },
            updateValue: function (_val) {
                this.numVal = _val > this.max ? this.max : _val < this.min ? this.min : _val;
                this.$emit('input',this.numVal);
            },
            inputChange: function (event) {
                let _val = event.target.value.trim();

                if(isNumVal(_val)){
                    _val = Number(_val);
                    this.updateValue(_val);
                }else{
                    event.target.value = this.numVal;
                }
            }
        }
    });
    new Vue({
        el: '#app',
        data:{
            value: 5
        }
    });
</script>
</html>